package org.opencv.SDK;

import android.util.Pair;
import android.util.TimingLogger;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.FastResultBean;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class TemplateMatching {
    private static final String LOG_TAG = "TemplateMatching";
    public static final int MATCHING_METHOD_DEFAULT = 5;
    public static final int MAX_LEVEL_AUTO = -1;
    private static final String TAG = "TemplateMatching";

    private static boolean shouldContinueMatching(int i, int i2) {
        if (i != i2 || i == 0) {
            return i2 > 2 && i == i2 - 1;
        }
        return true;
    }

    public static FastResultBean fastTemplateMatching(Mat mat, Mat mat2, int i, float f, float f2, int i2) {
        int i3;
        TimingLogger timingLogger = new TimingLogger("TemplateMatching", "fast_tm");
        if (i2 == -1) {
            i3 = selectPyramidLevel(mat, mat2);
            timingLogger.addSplit("selectPyramidLevel:" + i3);
        } else {
            i3 = i2;
        }
        double d = 0.0d;
        Mat pyramidDownAtLevel = getPyramidDownAtLevel(mat, i3);
        Mat pyramidDownAtLevel2 = getPyramidDownAtLevel(mat2, i3);
        Point point = null;
        Mat mat3 = null;
        for (int i4 = 0; i4 < 30; i4++) {
            release(mat3);
            mat3 = matchTemplate(pyramidDownAtLevel, pyramidDownAtLevel2, i);
            Pair<Point, Double> bestMatched = getBestMatched(mat3, i, f);
            point = (Point) bestMatched.first;
            d = ((Double) bestMatched.second).doubleValue();
            Imgproc.rectangle(pyramidDownAtLevel, point, new Point(point.x + ((double) pyramidDownAtLevel2.cols()), point.y + ((double) pyramidDownAtLevel2.rows())), new Scalar(0.0d, 255.0d, 0.0d));
            Imgcodecs.imwrite("/storage/emulated/0/AAAB/result.png", pyramidDownAtLevel);
        }
        pyramidDownAtLevel.release();
        pyramidDownAtLevel2.release();
        return new FastResultBean((int) point.x, (int) point.y, 0, 0, (int) (d * 100.0d));
    }

    private static Mat getPyramidDownAtLevel(Mat mat, int i) {
        if (i == 0) {
            return mat;
        }
        int cols = mat.cols();
        int rows = mat.rows();
        for (int i2 = 0; i2 < i; i2++) {
            cols = (cols + 1) / 2;
            rows = (rows + 1) / 2;
        }
        Mat mat2 = new Mat(rows, cols, mat.type());
        Imgproc.resize(mat, mat2, new Size((double) cols, (double) rows));
        return mat2;
    }

    private static void pyrUp(Point point, int i) {
        for (int i2 = 0; i2 < i; i2++) {
            point.x *= 2.0d;
            point.y *= 2.0d;
        }
    }

    private static Rect getROI(Point point, Mat mat, Mat mat2) {
        int max = Math.max(0, (int) ((point.x * 2.0d) - ((double) (mat2.cols() / 4))));
        int max2 = Math.max(0, (int) ((point.y * 2.0d) - ((double) (mat2.rows() / 4))));
        int cols = (int) (((double) mat2.cols()) * 1.5d);
        int rows = (int) (((double) mat2.rows()) * 1.5d);
        if (max + cols >= mat.cols()) {
            cols = (mat.cols() - max) - 1;
        }
        if (max2 + rows >= mat.rows()) {
            rows = (mat.rows() - max2) - 1;
        }
        return new Rect(max, max2, cols, rows);
    }

    private static int selectPyramidLevel(Mat mat, Mat mat2) {
        int log = (int) (Math.log((double) (min(mat.rows(), mat.cols(), mat2.rows(), mat2.cols()) / 16)) / Math.log(2.0d));
        if (log < 0) {
            return 0;
        }
        return Math.min(6, log);
    }

    public static int min(int... iArr) {
        int i = iArr[0];
        for (int i2 = 1; i2 < iArr.length; i2++) {
            if (iArr[i2] < i) {
                i = iArr[i2];
            }
        }
        return i;
    }

    public static Mat matchTemplate(Mat mat, Mat mat2, int i) {
        Mat mat3 = new Mat((mat.rows() - mat2.rows()) + 1, (mat.cols() - mat2.cols()) + 1, CvType.CV_32FC1);
        Imgproc.matchTemplate(mat, mat2, mat3, i);
        return mat3;
    }

    public static Pair<Point, Double> getBestMatched(Mat mat, int i, float f) {
        Point point;
        double d;
        TimingLogger timingLogger = new TimingLogger("TemplateMatching", "best_matched_point");
        Core.MinMaxLocResult minMaxLoc = Core.minMaxLoc(mat);
        timingLogger.addSplit("minMaxLoc");
        if (i == 0 || i == 1) {
            point = minMaxLoc.minLoc;
            d = -minMaxLoc.minVal;
        } else {
            point = minMaxLoc.maxLoc;
            d = minMaxLoc.maxVal;
        }
        timingLogger.addSplit("value:" + d);
        timingLogger.dumpToLog();
        return new Pair<>(point, Double.valueOf(d));
    }

    private static void release(Mat mat) {
        if (mat != null) {
            mat.release();
        }
    }

    public static FastResultBean fastTemplateMatching01(Mat mat, Mat mat2, int i, float f, float f2, int i2) {
        int i3;
        int i4;
        Mat mat3;
        int i5 = i;
        float f3 = f;
        TimingLogger timingLogger = new TimingLogger("TemplateMatching", "fast_tm");
        if (i2 == -1) {
            i3 = selectPyramidLevel(mat, mat2);
            timingLogger.addSplit("selectPyramidLevel:" + i3);
        } else {
            i3 = i2;
        }
        double d = 0.0d;
        boolean z = true;
        int i6 = i3;
        Point point = null;
        Mat mat4 = null;
        while (true) {
            if (i6 < 0) {
                break;
            }
            Mat pyramidDownAtLevel = getPyramidDownAtLevel(mat, i6);
            Mat pyramidDownAtLevel2 = getPyramidDownAtLevel(mat2, i6);
            if (point == null) {
                if (!z && !shouldContinueMatching(i6, i3)) {
                    break;
                }
                release(mat4);
                Mat matchTemplate = matchTemplate(pyramidDownAtLevel, pyramidDownAtLevel2, i5);
                Pair<Point, Double> bestMatched = getBestMatched(matchTemplate, i5, f3);
                Point point2 = (Point) bestMatched.first;
                mat3 = matchTemplate;
                d = ((Double) bestMatched.second).doubleValue();
                point = point2;
                i4 = i6;
            } else {
                Rect roi = getROI(point, pyramidDownAtLevel, pyramidDownAtLevel2);
                release(mat4);
                Mat mat5 = new Mat(pyramidDownAtLevel, roi);
                mat3 = matchTemplate(mat5, pyramidDownAtLevel2, i5);
                release(mat5);
                Pair<Point, Double> bestMatched2 = getBestMatched(mat3, i5, f3);
                ((Double) bestMatched2.second).doubleValue();
                point = (Point) bestMatched2.first;
                double doubleValue = ((Double) bestMatched2.second).doubleValue();
                i4 = i6;
                point.x += (double) roi.x;
                point.y += (double) roi.y;
                d = doubleValue;
            }
            if (pyramidDownAtLevel != mat) {
                release(pyramidDownAtLevel);
            }
            if (pyramidDownAtLevel2 != mat2) {
                pyramidDownAtLevel2.release();
            }
            if (d >= ((double) f2)) {
                pyrUp(point, i4);
                break;
            }
            timingLogger.addSplit("level:" + i4 + " point:" + point);
            i6 = i4 + -1;
            i5 = i;
            f3 = f;
            mat4 = mat3;
            z = false;
        }
        timingLogger.addSplit("result:" + point);
        timingLogger.dumpToLog();
        if (d < ((double) f2)) {
            return null;
        }
        return new FastResultBean((int) point.x, (int) point.y, 0, 0, (int) (d * 100.0d));
    }
}
